using System;
using System.Threading;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.USBHost;
using Melody_Glider.GUIContent;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.IO;

namespace Melody_Glider
{
    class USB
    {
        private readonly SystemState _conditions;
        private readonly GUI _gui;
        private static PersistentStorage _storage;

        public USB(GUI gui, SystemState conditions)
        {
            _conditions = conditions;
            _gui = gui;
        }

        public void SubscribeEvents()
        {
            USBHostController.DeviceConnectedEvent += DeviceConnectedEvent;
            USBHostController.DeviceDisconnectedEvent += DeviceDisconnectedEvent;

            RemovableMedia.Insert += RemovableMediaInsert;
            RemovableMedia.Eject += RemovableMediaEject;
        }

        private void DeviceConnectedEvent(USBH_Device device)
        {
            if (device.TYPE != USBH_DeviceType.MassStorage)
                return;

            try
            {
                _storage = new PersistentStorage(device);
                _storage.MountFileSystem();
            }
            catch (Exception)
            {
                Beep(4, 50, 100, 4000);
            }
        }

        private void DeviceDisconnectedEvent(USBH_Device device)
        {
            _gui.DispMsg("Please insert USB flash drive");
        }

        private void RemovableMediaInsert(object sender, MediaEventArgs e)
        {
            if (e.Volume.IsFormatted)
            {
                _conditions.Drive = e;
                Beep(1, 100, 0, 4000); //"War elephant ready"
                
                _gui.MainMenuWindow.ShowButtons();
                _gui.MainMenuWindow.DispMsg("");
            }
            else
            {
                Beep(4, 50, 100, 4000);
            }
        }

        private void RemovableMediaEject(object sender, MediaEventArgs e)
        {
            _storage.Dispose();

            if (_gui.MainMenuWindow.IsMain()) //to prevent window from being invalidated twice after pressing "eject" button
                return;

            //the code below is to get back to the main window if user ejects the thumbdrive in a wrong way, i.eg. during melody creation
            _gui.MainMenuWindow.HideButtons();
            _gui.MainMenuWindow.SetToMain();
        }

        public static void UnmountFileSystem()
        {
            _storage.UnmountFileSystem();
        }

        private static void Beep(int times, uint hi, int lo, uint freq)
        {
            for (var i = 0; i < times; i++)
            {
                Utility.Piezo(freq, hi);
                Thread.Sleep(lo);
            }
        }
    }
}
